package com.infoauto.opc.gateway.opc.factory;

import com.infoauto.opc.gateway.model.OpcInterfaceGroup;
import com.infoauto.opc.gateway.model.OpcInterfaceNode;
import com.infoauto.opc.gateway.opc.MessageHandler;
import com.infoauto.opc.gateway.opc.model.INodeType;
import com.infoauto.opc.gateway.opc.model.MqttInterface;
import com.infoauto.opc.gateway.opc.model.MqttInterfaceNode;
import com.infoauto.opc.gateway.opc.model.WebInterfaceNode;
import com.infoauto.opc.gateway.opc.utils.SpringContextUtils;
import com.infoauto.opc.gateway.service.OpcInterfaceGroupsService;
import com.infoauto.opc.gateway.service.OpcInterfaceNodesService;
import org.eclipse.milo.opcua.stack.core.types.builtin.Variant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * MQTT接口工厂类
 **/
public class MqttInterfaceNodeFactory {
    @Autowired
    private SpringContextUtils springContextUtils;
    // <summary>
    /// Manager实例
    /// </summary>
    private static MqttInterfaceNodeFactory _manager;
    /// <summary>
    /// 锁定实例
    /// </summary>
    private static Object oClassLock = new Object();

    /// <summary>
    /// 得到该实例
    /// </summary>
    /// <returns></returns>
    public static MqttInterfaceNodeFactory Instance() {
        synchronized (oClassLock) //加锁只生成一个实例
        {
            if (_manager == null) {
                _manager = new MqttInterfaceNodeFactory();
            }
        }
        return _manager;
    }

    /// <summary>
    /// 私有的构造函数,防止从外部实例化
    /// </summary>
    private MqttInterfaceNodeFactory() {
        mapInterfaces = Collections.synchronizedMap(new HashMap<>());
    }

    /// <summary>
    /// 得到该实例
    /// </summary>
    public static MqttInterfaceNodeFactory This() {
        return Instance();
    }

    private final Logger logger = LoggerFactory.getLogger(getClass());
    private Map<Integer, MqttInterface> mapInterfaces;

    /**
     * 添加接口
     */
    public void addInterface(int interfaceID, MqttInterface intf) {
        if (!this.mapInterfaces.containsKey(interfaceID))
            this.mapInterfaces.put(interfaceID, intf);
    }

    /**
     * 添加点到对应接口中
     */
    public void addNodeToInterface(int interfaceID, MqttInterfaceNode node) {
        MqttInterface oi = this.mapInterfaces.get(interfaceID);
        if (oi != null) {
            node.setOpcInterface(oi);
            switch (INodeType.valueOf(node.getNodeType())) {
                case OPC:
                    SubscribeNodeFactory.This().matchInterfaceNode(node);
                    break;
                case THIRD:
                    WebInterfaceNodeFactory.This().matchMqttInterfaceNode(node);
                    break;
                case LABEL:
                    // TODO 当节点是静态文本的时候，节点值等于默认静态文本值
                    // node.setNodeValue(new Variant(node.getLabelValue()));
                    break;
                default:
                    break;
            }
            if (oi.getNodes() == null) {
                oi.setNodes(Collections.synchronizedMap(new HashMap<>()));
            }
            oi.getNodes().put(node.getNodeID(), node);
        }
    }

    /**
     * 加载MQTT_OPC ANDON数据配置的接口
     **/
    public void loadMqttInterfaceGroups() {
        OpcInterfaceGroupsService uss = springContextUtils.getBean(OpcInterfaceGroupsService.class);
        List<OpcInterfaceGroup> groups = uss.select(OpcClientFactory.This().getSiteCode());
        for (OpcInterfaceGroup oig : groups) {
            logger.info("Loading OpcInterfaceGroups InterfaceID = {} InterfaceName = {}",
                    oig.getInterfaceID(),
                    oig.getInterfaceName());

            if (!mapInterfaces.containsKey(oig.getInterfaceID())) {
                MqttInterface intf = new MqttInterface();//创建ANDON数据配置的接口并且赋值
                intf.setInterfaceID(oig.getInterfaceID());//接口ID
                intf.setInterfaceName(oig.getInterfaceName());//接口名称
                intf.setLabelName(oig.getLabelName());//文本名称
                intf.setLabelValue(oig.getLabelValue());//文本值
                mapInterfaces.put(oig.getInterfaceID(), intf);//赋值ANDON数据配置的接口集合
            }
        }
    }

    /**
     * 加载MQTT_OPC ANDON数据配置的接口属性集合
     */
    public void loadMqttInterfaceNodes() {
        OpcInterfaceNodesService usns = springContextUtils.getBean(OpcInterfaceNodesService.class);
        List<OpcInterfaceNode> nodes = usns.select(OpcClientFactory.This().getSiteCode());//查询ANDON数据配置的接口节点属性集合
        for (OpcInterfaceNode oin : nodes) {
            MqttInterfaceNode node = new MqttInterfaceNode();//ANDON数据配置接口的节点属性实体；如果是给第三方配置接口的属性赋值
            if(oin.getNodeType() == 3 && oin.getThirdNo() !=0) { //判断是否是第三方接口类型的数据
                WebInterfaceNode wn = new WebInterfaceNode();//第三方配置接口的属性实体
                wn.setThirdNodeID(oin.getThirdNo());
                node.setWebInterfaceNode(wn);//给第三方配置接口的属性赋值
            }

            node.setLabel(oin.getLabel());//标签名
            node.setNodeID(oin.getNodeID());//节点主键
            node.setOpcNodeID(oin.getOpcNodeID());//OPC节点的ID
            node.setNodeType(oin.getNodeType());//节点类型,4表示OPC,2表示文本,3表示第三方接口
            node.setTagName(oin.getTagName());//接口属性名称，用于MQ推送的json变量名用
            node.setPicUrl(oin.getPicUrl());//图片的URL
            if (oin.getNodeType() == 2) {
                // TODO 当节点是静态文本的时候，节点值等于默认静态文本值
                node.setNodeValue(new Variant(oin.getValue()));
            }
            this.addNodeToInterface(oin.getInterfaceID(), node);//添加点到对应接口中
        }
    }

    /**
     * 根据接口名称，发布接口消息
     * interfaceName 接口名称
     **/
    public void publishMessage(String interfaceName) {
        for (MqttInterface oi : this.mapInterfaces.values()) {
            if (oi.getInterfaceName().equals(interfaceName)) {
                MessageHandler.This().MqttProcessor(oi.getInterfaceName(), oi.toString());
            }
        }
    }

    /***
     * 删除节点
     * */
    public void clearNodes(){
        if(this.mapInterfaces!=null){
            this.mapInterfaces.clear();
        }
    }


    public String  getMessageByInterfaceId(Integer interfaceID) {
        MqttInterface oi = this.mapInterfaces.get(interfaceID);
        /*for (MqttInterface oi : this.mapInterfaces.values()) {
            if (oi.getInterfaceID()==interfaceID) {
                return oi.toString();
            }
        }*/
        return oi.toString();
    }

}
